﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Lynn.Infastructure.Net.Http;
using System.Net;
using Polly;
using System.Threading.Tasks;
using Lynn.Infastructure.Net.MQTT;
using MQTTnet;

namespace Lynn.Infastructure.Net
{
    public static class NetWorkService
    {
        /// <summary>
        /// 添加http请求
        /// </summary>
        /// <param name="services"></param>
        /// <param name="option"></param>
        /// <returns></returns>
        public static IServiceCollection AddHttpService(this IServiceCollection services, Action<HttpOption> option)
        {
            var opt = new HttpOption();
            option.Invoke(opt);
            services.AddHttpClient(opt.DefaultName).ConfigureHttpMessageHandlerBuilder((x) =>
            {
                if (opt.SSL != null)
                {
                    var handler = new HttpClientHandler();
                    handler.ClientCertificates.Add(opt.SSL.Cert);
                    x.PrimaryHandler = handler;
                }
            }).ConfigureHttpClient(x =>
            {
                x.Timeout = TimeSpan.FromMilliseconds(opt.TimeOut);
                if (opt.Identity != null) {
                    opt.Identity.ToAuth(x);
                }
            }).AddTransientHttpErrorPolicy(builder =>
            {
                return builder.Or<TaskCanceledException>()
                    .Or<OperationCanceledException>()
                    .Or<TimeoutException>()
                    .OrResult(res => res.StatusCode == HttpStatusCode.TooManyRequests)
                    .RetryAsync(opt.ReTry);
            });
            services.TryAddSingleton(typeof(HttpOption), c => opt);
            services.TryAddScoped<HttpWork>();
            return services;
        }
        public static IServiceCollection AddMqttService<Handle>(this IServiceCollection services, Func<IMQTTOptions> option) where Handle : MqttHandleAbstract, new()
        {
            var opt = option.Invoke();
            var factory = new MqttFactory();
            var handle = new Handle();
            var client = new MQTTClient<Handle>(factory, opt, handle);
            Task.Run(async () => await client.Start()).Wait();
            services.TryAddSingleton(handle);
            return services;
        }
    }
}
